package com.example.exercise.rule;

import com.example.exercise.common.Pojo;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.QueryResults;
import org.kie.api.runtime.rule.QueryResultsRow;

import java.util.ArrayList;
import java.util.List;

public class DroolsUtils {

    public static <T extends Pojo> boolean match(T data, String rule) {
        String initializedRule = DroolsInitialization.preHandle(data, rule);
        if(initializedRule == null){

        }
        String ruleString = "import " + data.getClass().getName() + ";\n" +
                "rule \"matchOneData\"\nwhen\n" +
                data.getClass().getSimpleName() +
                "(" + initializedRule + ")\nthen\nend\n";
        KieSession kieSession = DroolsInitialization.getKieSession(ruleString);
        kieSession.insert(data);
        int num = kieSession.fireAllRules();
        kieSession.dispose();
        return num > 0;
    }

    @SuppressWarnings("unchecked")
    public static <T extends Pojo> List<T> match(List<T> dataList, String rule) {
        if(dataList.isEmpty()) {
            return dataList;
        }
        T data = dataList.get(0);

        Class<?> clazz = data.getClass();
        String initializedRule = DroolsInitialization.preHandle(data, rule);
        if(initializedRule == null){

        }

        String ruleString = "import " + clazz.getName() + ";\n" +
                "import java.util.List;\n" +
                "rule \"matchData\"\nwhen\n    $list : List(size > 0)\n$data : " +
                clazz.getSimpleName() +
                "(" + initializedRule + ") from $list\nthen\n    insert($data);\nend\n" +
                "query \"queryMatchedData\"\n    $data : " +
                clazz.getSimpleName() + "(" + initializedRule + ");\nend\n";
        KieSession kieSession = DroolsInitialization.getKieSession(ruleString);
        kieSession.insert(dataList);
        kieSession.fireAllRules();
        QueryResults queryResultsRows = kieSession.getQueryResults("queryMatchedData");
        List<T> list = new ArrayList<>();
        for (QueryResultsRow queryResultsRow : queryResultsRows) {
            list.add((T) queryResultsRow.get("$data"));
        }
        kieSession.dispose();
        return list;
    }

    public static <T extends Pojo> List<Object> calculate(List<T> dataList, String rule, String importStr, String functionStr) {
        Class<?> clazz = dataList.get(0).getClass();
        String ruleString = "import " + clazz.getName() + ";\n" +
                "import java.util.List;\n";
        if (importStr != null && !"".equals(importStr.trim())) {
            ruleString += importStr + "\n";
        }
        if (functionStr != null && !"".equals(functionStr.trim())) {
            ruleString += functionStr + "\n";
        }
        ruleString += "global List result;\n";
        ruleString += "rule \"matchData\"\nwhen\n    $list : List(size > 0)\ndata : " +
                clazz.getSimpleName() + "() from $list\nthen\n    " + rule + "\nend\n";
        KieSession kieSession = DroolsInitialization.getKieSession(ruleString);
        List<Object> result = new ArrayList<>();
        kieSession.setGlobal("result", result);
        kieSession.insert(dataList);
        kieSession.fireAllRules();
        return result;
    }

    public static <T extends Pojo> Object calculate(T data, String rule, String importStr, String functionStr) {
        Class<?> clazz = data.getClass();
        String ruleString = "import " + clazz.getName() + ";\n" +
                "import java.util.List;\n";
        if (importStr != null && !"".equals(importStr.trim())) {
            ruleString += importStr + "\n";
        }
        if (functionStr != null && !"".equals(functionStr.trim())) {
            ruleString += functionStr + "\n";
        }
        ruleString += "global List result;\n";
        ruleString += "rule \"matchData\"\nwhen\n    data : " +
                clazz.getSimpleName() + "()\nthen\n    " + rule + "\nend\n";
        KieSession kieSession = DroolsInitialization.getKieSession(ruleString);
        List<Object> result = new ArrayList<>();
        kieSession.setGlobal("result", result);
        kieSession.insert(data);
        kieSession.fireAllRules();
        if (!result.isEmpty()) {
            return result.get(0);
        }
        return null;
    }
}
